#include "mq_channel.hpp"

namespace pprmq
{
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>;
        Connection(const VirtualHost::ptr &host, 
                const ConsumerManager::ptr &cmp, 
                const ProtobufCodecPtr &codec, 
                const muduo::net::TcpConnectionPtr &conn,
                const threadpool::ptr &pool)
                :_conn(conn)
                ,_codec(codec)
                ,_cmp(cmp)
                ,_host(host)
                ,_pool(pool)
                ,_channels(std::make_shared<ChannelManager>()){}
        void openChannel(const OpenChannelRequestPtr& req)
        {
            //1. 判断信道ID是否重复,创建信道
            bool ret = _channels->openChannel(req->cid(),_conn,_codec,_cmp,_pool,_host);
            if(ret == false)
            {
                DLOG("创建信道的时候,信道ID重复了");
                return basicResponse(false,req->rid(),req->cid());
            }
            DLOG("%s 信道创建成功", req->cid().c_str());
            //2. 给客户端进行回复
            return basicResponse(true,req->rid(),req->cid());   
        }

        void closeChannel(const CloseChannelRequestPtr& req)
        {
            _channels->closeChannel(req->cid());
            return basicResponse(true,req->rid(),req->cid());
        }

        Channel::ptr getChannel(const std::string &cid)
        {
            return _channels->getChannel(cid);
        }
    private:
        // 构造通用的操作结果响应，统一格式便于客户端解析
        void basicResponse(bool ok, const std::string &rid, const std::string &cid)
        {
            basicCommonResponse resp;
            resp.set_rid(rid); // 请求ID，用于匹配请求与响应
            resp.set_cid(cid); // 信道ID，标识响应所属的信道
            resp.set_ok(ok); // 操作结果（成功/失败）
            _codec->send(_conn,resp);
        }
    private:
        muduo::net::TcpConnectionPtr _conn; // muduo库的Tcp管理，网络通信
        ProtobufCodecPtr _codec; // 用于处理序列化和反序列化
        ConsumerManager::ptr _cmp; // 消费者管理器，管理订阅队列的消费者
        VirtualHost::ptr _host; // 管理交换机，队列等核心资源
        threadpool::ptr _pool; // 线程池，异步处理消息消费任务，避免网络IO线程
        ChannelManager::ptr _channels; 
    };

    class ConnectionManager 
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>;
        ConnectionManager(){}

        void newConnection(const VirtualHost::ptr &host, 
                const ConsumerManager::ptr &cmp, 
                const ProtobufCodecPtr &codec, 
                const muduo::net::TcpConnectionPtr &conn,
                const threadpool::ptr &pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it != _conns.end())
            {
                // 存在
                return ;
            }
            // 不存在就创建
            Connection::ptr self_conn = std::make_shared<Connection>(host,cmp,codec,conn,pool);
            _conns.insert(std::make_pair(conn,self_conn));
        }

        void delConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _conns.erase(conn);
        }

        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end())
            {
                // 不存在
                return Connection::ptr();
            }
            return it->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr,Connection::ptr> _conns;
    };
}